#!/usr/bin/perl 

# 20.11.2005 - added ability to download several URLs
# 20.11.2005 - added ability to recursively download files and dirs
# 25.11.2005 - recursive downloading now is wget-like :)

# defaults:
$bs=8192;
$append=0;
$recurse=0;
$|=1;

foreach (@ARGV)
    {
    if    (/^-bs=(\d+)$/) {$bs=$1}
    elsif ((/^-ra$/)or(/^-ar$/)) {$append=$recurse=1}
    elsif (/^-a$/)         {$append=1}
    elsif (/^-r$/)         {$recurse=1}
       else {
    	    $src=$_;
	    if ($src=~/^\\\\/)
		{
		# lets translate windoze-like url to native format
		$src=~s!\\!/!g;
		$src="smb:".$src;
		}
	    $src=~s|/+$||; #strip possible slashes from end
	    push @sources, $src;
	    }
    }

if (!scalar(@sources))
    {
    die "Usage :\n$0 <NETFILE> [NETFILE .. NETFILE] [-bs=BS] [-a] [-r]
    NETFILE	Source file, i.e. smb://host/share/path/file or \\\\host\\share\\path\\file
    -bs=BS	BS will be count of bytes per read (block size). 8192 by default.
    -a		Destination will be appended, if exist. But by default, will be replaced.
    -r		If NETFILE is directory, all tree will be fetched with full structure. 
		If NETFILE is file, it will be fetched with full structure also.

options could be placed in any order\n";
    }

use Filesys::SmbClient;

$smb = new Filesys::SmbClient(username  => "guest",
                                 password  => "",
                                 workgroup => "SNET",
                                 debug     => 0);

foreach $src (@sources)
    {
    
    if (!$recurse)
	{#as usually without recursing
	$dst=$src;
	$dst=~s!^.*/([^/]+)$!$1!g;
	&fetch($src,".",$dst,$append);
	}
	else
	{# wow.. it is something new :) try recursing
	if (!content($src))
	    {# that is file . Fetch in strange directory
	    if ($src=~m!^smb://(.+)/([^/]+)$!)
		{
		$dir=$1;
		$dst=$2;
		&fetch($src,"./$dir",$dst,$append);
		}
	    }
	    elsif (scalar @CONTENT)
		{# that is dir and it is not empty
		foreach $srcrec (@CONTENT)
		    {
		    if ($srcrec=~m!^smb://(.+)/([^/]+)$!)
			{
			$dir=$1;
			$dst=$2;
			&fetch($srcrec,"./$dir",$dst,$append);
			}
		    }
		}
		else {print "$src is dir, but its empty, sorry"}
	}
    }
    
    
sub fetch
    {
    print "\n";
    # it downloads $src -> $dst (appends if $append)
    my $src=shift;    # url of file to fetch
    my $dir=shift;
    my $dst=$dir."/".shift;
    my $append=shift; #0/1
    
    my $time_begin;
    my $time_previous;
    my $ds_previous;
    my $data;
    my $percentage;
    my $speed;
    my $eta;
    my $ds;
    my $ss;
    my $tries=0; 
    
    print "$src -> $dst\n";

    my @tab = $smb->stat($src);

    if ($#tab == 0) 
	{print STDERR "Error in stat:", $!, "\n";return $tries}
	else
	{$ss=$tab[7];}

    if ($dir ne "\.") 
	{#quickly but dirty hack :-)
	system "mkdir -p '$dir'";
	}
    
    if ($append) 
	{open OUT, ">>$dst" or die "Can't open dst file:", $!, "\n";}
	else
	{open OUT,  ">$dst" or die "Can't open dst file:", $!, "\n";}
    $ds=(-s $dst);  #size of dst file

    while ($ss!=$ds)
	{
	$tries++;
	print "SRC/DST size = $ss/$ds , ";
	#sleep 1;
	my $fd = $smb->open($src) or next;
	print " open SRC: OK, ";
	$smb->seek($fd, $ds) ;
	print " seek SRC: OK\n";
	$time_begin=time();
	$time_previous=$time_begin;
	$ds_previous=$ds;
	    while ($data=$smb->read($fd,$bs) )
	    {
	    $ds+=syswrite OUT,$data;
	    $time=time();
	    if (($time-$time_previous)>1)
		{
		print "\x08"x8787;
		$percentage=(100*$ds/$ss);
		$speed=(($ds-$ds_previous)/($time-$time_previous)); #bytes/sec
		$speed+=0.001;
		$eta= (($ss-$ds)/$speed);
		printf "%7.3f%% , %7.3f kbytes/sec , ETA %.f sec %s" , $percentage,$speed/1024,$eta," "x10;
		$time_previous=time;
		$ds_previous=$ds;
		
		}	
	    }
        #print "\n";
	$smb->close($fd);
	}
    close OUT;
    print "SRC/DST size = $ss/$ds. Done by $tries tries\n";
    return $tries;
}



#&content("smb://10.16.80.2/free");


sub content
{
# it prints all files inside $current_dir
my $current_dir=shift;

my @dirs=();
my @files=();
my $dir;
my $file;
#my $fd = $smb->opendir("$current_dir");

if (my $fd = $smb->opendir("$current_dir"))
    {
    while (my $f = $smb->readdir_struct($fd)) 
	{
	#print " ==> begin processing '$current_dir'\n";
	if ($f->[0] == SMBC_DIR) 
	    {push @dirs,  $f->[1]}
    	    elsif ($f->[0] == SMBC_FILE) 
	    {push @files, $f->[1]}
	}
    close($fd);

    foreach $file (@files)
	{
	#print "*$current_dir/$file\n";
	push @CONTENT, "$current_dir/$file";
	#print "$current_dir/$file"."\n";
	}
    foreach $dir (@dirs)
	{
	if ($dir!~/^\.\.?$/) #exclude . and .. 
	    {
	    #print "[]$current_dir/$dir\n";
	    &content("$current_dir/$dir");
	    }
	}
    #print " <== end processing '$current_dir'\n";
    return 1;
    }
    else {print "that's file, not dir \n"; return 0;}
}
